//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "ddk.h"
#include "eltypes.h"
#include <tfssys.h>
#include <string.h>
#include <misc.h>

EXTERN_C Boolean GetDevDriver(
    /*[in]*/const wchar_t *pDevName,
    /*[out]*/PPDevDriver ppDev)
{
    assert(pDevName && ppDev);
    *ppDev = NULL;
    ECode ec = NOERROR;

    ec = DzFindService(pDevName, (IInterface **)ppDev);
    if (FAILED(ec)) {
        DPRINTF(("ERROR: failed to open device. device name<%S>\n" , pDevName));
        return FALSE;
    }

    assert(*ppDev);
    return TRUE;
}

EXTERN_C ECode ReadDevice(
    /*[in]*/const PDevDriver pDevDriver,
    /*[in]*/UInt64 u64Offset,
    /*[in]*/UInt32 uNumberOfBytesToRead,
    /*[out]*/PByte pBuffer,
    /*[out]*/UInt32 *pReadSize,
    /*[out]*/PVoid *pExtArg)
{
    assert(pDevDriver && pBuffer);
    UInt32 uReadSize = 0;
    ECode ec = NOERROR;

    MemoryBuf ebbData(pBuffer, uNumberOfBytesToRead);
    ec = pDevDriver->Read(u64Offset, uNumberOfBytesToRead, &ebbData, NULL);
    if (FAILED(ec)) {
        DPRINTF(("KTFS Warning:Read Device Failed.ec:0x%x. offset:%d, toRead:%d.\n",
            ec, u64Offset, uNumberOfBytesToRead));
        return ec;
    }
    uReadSize = ebbData.GetUsed();

    assert(uReadSize == uNumberOfBytesToRead);
    if (pReadSize) {
        *pReadSize = uReadSize;
    }
    return NOERROR;
}

EXTERN_C ECode WriteDevice(
    /*[in]*/const PDevDriver pDevDriver,
    /*[in]*/Int64 u64Offset,
    /*[in]*/UInt32 uSizeToWrite,
    /*[in]*/const PByte pBuffer,
    /*[out]*/Int32 *pSizeWritten,
    /*[out]*/PVoid *pExtArg)
{
    assert(pDevDriver && pBuffer);
    Int32 uSizeWritten = 0;
    ECode ec = NOERROR;

    MemoryBuf ebbData(pBuffer, uSizeToWrite);

    ec = pDevDriver->Write(u64Offset, ebbData, &uSizeWritten, NULL);

    if (FAILED(ec)) {
        DPRINTF(("KTFS Warning:Write Device Failed.ec:0x%x, offset:%I64d, toWrite:%u.\n",
            ec, u64Offset, uSizeToWrite));
        return ec;
    }
    assert(uSizeWritten == (Int32)uSizeToWrite);
    if (pSizeWritten) {
        *pSizeWritten = uSizeWritten;
    }
    return NOERROR;
}

ECode DeleteBlock(
    /*[in]*/const PDevDriver pDevDriver,
    /*[in]*/UInt32 sector,
    /*[in]*/UInt32 nblocks)
{
    ECode ec;
    MemoryBuf_<8> p;
    p.Copy((PByte)&sector, 4);
    p.Append((PByte)&nblocks, 4);

    ec = pDevDriver->Control(
            FTLControl_DeleteBlock, // 0x10000001
            p,
            NULL,
            NULL);
    return NOERROR;
}
